import 'dart:isolate';

import 'package:collection/collection.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:im_app/im/page/bloc/MessageListCubit.dart';
import 'package:im_app/im/service/ImMessageReadService.dart';
import 'package:im_app/im/socket/service/RpcSendDataService.dart';
import 'package:im_app/im/util/CollectionUtil.dart';
import 'package:im_app/im/util/DialogUtil.dart';
import 'package:im_app/im/util/ImConstant.dart';
import 'package:im_app/im/util/ImSingleton.dart';
import 'package:im_app/im/webrtc/WebRtcInvitationDialog.dart';
import 'package:logger/logger.dart';

import '../dao/ImSessionDao.dart';
import '../page/bloc/WebRtcCubit.dart';
import '../page/sub/WebRtcAudioPage.dart';
import '../page/sub/WebRtcVideoPage.dart';
import '../page/view/WebRtcAudioView.dart';
import '../page/view/WebRtcFloatingView.dart';
import '../page/view/WebRtcVideoView.dart';
import '../pojo/ImPojo.dart';
import '../socket/dto/business/WebRtcData.dart';

class UiUtil {

  static final _logger = Logger(printer: PrettyPrinter(),);

  static void setLoginUser(ImUser user) {
    ImSingleton.getInstance().session.putData(ImConstant.IM_LOGIN_USER, user);
  }

  static ImUser getLoginUser() {
    return ImSingleton.getInstance().session.getData(ImConstant.IM_LOGIN_USER)! as ImUser;
  }

  static void uiShowMessages(List<ImMessage> messages) async {
    if (messages.isEmpty) return;
    _logger.i("uiShowMessage start!");
    String userId = ImSingleton.getInstance().session.userId!;

    await handleHotMessage(userId, messages);

    if (ImSingleton.getInstance().messageListCubit != null) {
      List<ImMessage> canShowMessages = CollectionUtil.filter(messages, ImSingleton.getInstance().messageListCubit!.canShowMessage);

      ImSingleton.getInstance().messageListCubit?.add(MessageListAddMessagesEvent(canShowMessages));

      if (canShowMessages.isNotEmpty) {
        var messageReadService = ImMessageReadService.getInstance();
        messageReadService.asyHandleReadMessage(canShowMessages[0].sessionId!, userId, canShowMessages);
      }
    }
  }

  static uiAddMessages(List<ImMessage> messages) {
    if (messages.isEmpty) return;
    if (ImSingleton.getInstance().messageListCubit != null) {
      List<ImMessage> canShowMessages = CollectionUtil.filter(messages, ImSingleton.getInstance().messageListCubit!.canShowMessage);

      ImSingleton.getInstance().messageListCubit?.add(MessageListAddMessagesEvent(canShowMessages));
    }
  }

  static void uiShowMessage(ImMessage message) {
    uiShowMessages([message]);
  }

  static void uiUpdateMessage(ImMessage message) {
    ImSingleton.getInstance().messageListCubit?.add(MessageListUpdateMessagesEvent([message]));
  }

  static void uiUpdateFileUploadProgress(ImMessage message, double progress) {
    ImSingleton.getInstance().messageListCubit?.add(MessageListUploadProgressEvent(message, progress));
  }

  static void uiUpdateMessages(List<ImMessage> messages) {
    ImSingleton.getInstance().messageListCubit?.add(MessageListUpdateMessagesEvent(messages));
  }

  static void uiDeleteMessages(List<ImMessage> messages) {
    ImSingleton.getInstance().messageListCubit?.add(MessageListRemoveMessagesEvent(messages));
  }

  static void uiCleanMessages() {
    ImSingleton.getInstance().messageListCubit?.add(MessageListCleanMessagesEvent());
  }

  static void uiChangeSession(ImSession session) {
    if (ImSingleton.getInstance().sessionListCubit?.has(session)??false) {
      ImSingleton.getInstance().sessionListCubit?.changeSession(session);
    } else {
      ImSingleton.getInstance().sessionListCubit?.addSession(session);
    }
  }

  static void uiChangeHotMessage(String userId) {
    ImSingleton.getInstance().sessionListCubit?.reload(userId);
  }

  static bool uiAddSession(ImSession session) {
    if (ImSingleton.getInstance().sessionListCubit != null) {
      if (!ImSingleton.getInstance().sessionListCubit!.has(session!)) {
        ImSingleton.getInstance().sessionListCubit!.addSession(session);
        return true;
      }
    }
    return false;
  }

  static void uiShowSession(ImSession session) {
    if (ImSingleton.getInstance().sessionListCubit != null) {
      if (!ImSingleton.getInstance().sessionListCubit!.has(session!)) {
        ImSingleton.getInstance().sessionListCubit!.addSession(session);
      } else {
        ImSingleton.getInstance().sessionListCubit!.changeSession(session);
      }
    }
  }

  /// 更新最新消息
  static Future<void> handleHotMessage(String userId, List<ImMessage> messages) async {
    List<ImMessage> hotMessages = messages.where((m) => m.isReceiver(userId)).toList(growable: false);
    if (hotMessages.isNotEmpty) {
      Map<int, List<ImMessage>> messageMap = groupBy(hotMessages, (m) => m.sessionId!);
      var sessionDao =  ImSessionDao();
      for (var key in messageMap.keys) {
        int hotMessageSize = messageMap[key]!.length;

        if (hotMessageSize > 0) {
          await sessionDao.incHotMessageNum(key, hotMessageSize);

          var imSession = await sessionDao.getById(key);
          await sessionDao.loadGroupInfo(imSession!);
          _logger.i("hotMessageTotal: ${imSession!.hotMessageTotal??0}, $hotMessageSize, ${imSession!.id}, "
              "${Isolate.current.hashCode}");
          UiUtil.uiChangeSession(imSession!);
        }
      }
      ImSingleton.getInstance().sessionListCubit?.increaseHotMessageTotal(hotMessages.length);
    }
  }

  static showSnackBar(BuildContext context, String messageContent) {
    if (context.mounted) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(messageContent, style: const TextStyle(color: Colors.black),),
          backgroundColor: ImConstant.IM_MAIN_BACKGROUND_COLOR,
          showCloseIcon: true,
          closeIconColor: Colors.black38,
        ),
      );
    }
  }

  // 显示邀请： 接受或拒绝
  static showInvitation(WebRtcInvitationReq invitationReq) {
    var context = ImSingleton.getInstance().mainContext!;
    var webRtcCubit = context.read<WebRtcCubit>();

    if (invitationReq.chatType == ChatType.audio) {
      var dialog = WebRtcAudioView(invitationReq: invitationReq,);
      OverlayEntry entry = showOverlay(context, dialog);
      dialog.overlayEntry = entry;
      var overlayEntry = ImSingleton.getInstance().session.getData("webRtcOverlay");
      if (overlayEntry != null) {
        removeOverlay(overlayEntry as OverlayEntry);
      }
      ImSingleton.getInstance().session.putData("webRtcOverlay", entry);
      webRtcCubit.add(WebRtcInvitationEvent(invitationReq.userIds, entry));
    } else {
      var dialog = WebRtcVideoView(invitationReq: invitationReq,);
      OverlayEntry entry = showOverlay(context, dialog);
      dialog.overlayEntry = entry;
      var overlayEntry = ImSingleton.getInstance().session.getData("webRtcOverlay");
      if (overlayEntry != null) {
        removeOverlay(overlayEntry as OverlayEntry);
      }
      ImSingleton.getInstance().session.putData("webRtcOverlay", entry);
      webRtcCubit.add(WebRtcInvitationEvent(invitationReq.userIds, entry));
    }

  }
}